home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 June: Reference Library / Dev.CD Jun 00 RL Disk 1.toast / pc / technical documentation / develop / develop issue 27 / develop issue 27 code / internet config assistant / toolkit / cdialogs.cp < prev    next >
Encoding:
Text File  |  1996-06-30  |  24.0 KB  |  1,125 lines

  1. /*
  2.     File:        CDialogs.cp
  3.  
  4.     Contains:    Layer built on top of the Dialog Manager
  5.  
  6.     Written by:    Arno Gourdol
  7.  
  8.     Copyright:    © 1994-1996 by Apple Computer, Inc., all rights reserved.
  9.  
  10. */
  11.  
  12. #include "CDialogs.h"
  13. #include "assert.h"
  14.  
  15. #include <LowMem.h> // for LMGetGrayRgn()
  16. #include <Memory.h>
  17. #include <Script.h>
  18.  
  19. #include "CFonts.h"
  20. #include "HTMLParser.h"
  21.  
  22.  
  23. CDialog *CDialog::gDialogList = NULL;
  24.  
  25.  
  26.  
  27. class LazyHandle
  28. {
  29. public:
  30.     inline LazyHandle(void);
  31.     inline ~LazyHandle();
  32.     
  33.     inline void SetSize(Size size);
  34.     inline Size GetSize(void);
  35.     inline operator Handle(void) { return fHandle;};
  36.     inline Handle Set(void* pointer, Size size);
  37. private:
  38.     Handle fHandle;
  39. };
  40.  
  41.  
  42.  
  43. inline LazyHandle::LazyHandle(void) :
  44.     fHandle(NULL)
  45. {
  46. }
  47.  
  48.  
  49.  
  50. inline LazyHandle::~LazyHandle()
  51. {
  52.     if (fHandle != NULL)
  53.     {
  54.         DisposeHandle(fHandle);
  55.     }
  56. }
  57.  
  58.  
  59.     
  60. inline void LazyHandle::SetSize(Size size)
  61. {
  62.     if (fHandle == NULL)
  63.     {
  64.         fHandle = NewHandle(size);
  65.     }
  66.     else
  67.     {
  68.         SetHandleSize(fHandle, size);
  69.         if (MemError() != noErr)
  70.         {
  71.             if (fHandle != NULL)
  72.                 DisposeHandle(fHandle);
  73.             fHandle = NULL;
  74.         }
  75.     }
  76. }
  77.  
  78. inline Size LazyHandle::GetSize(void)
  79. {
  80.     if (fHandle == NULL)
  81.     {
  82.         return 0;
  83.     }
  84.     else
  85.     {
  86.         return GetHandleSize(fHandle);
  87.     }
  88. }
  89.  
  90.  
  91.  
  92. inline Handle LazyHandle::Set(void* pointer, Size size)
  93. {
  94.     SetSize(size);
  95.     if (fHandle != NULL)
  96.         ::BlockMoveData(pointer, *fHandle, size);
  97.     return fHandle;
  98. }
  99.  
  100.  
  101.  
  102. // --------------------------------------------------------------------
  103. // CDialog
  104. // --------------------------------------------------------------------
  105.  
  106. CDialog::CDialog(SInt16 dialogID, FontCode fontCode) :
  107.     fDialogID(dialogID),
  108.     fDialog(NULL),
  109.     fDefaultButton(-1),
  110.     fCancelButton(-1),
  111.     fNextDialog(NULL),
  112.     fNumShortcuts(0),
  113.     fShortcuts(NULL)
  114. {
  115.     for (int i = 0; i < kDialogParametersCount; i++)
  116.     {
  117.         fParameters[i].key[0] = 0;
  118.         fParameters[i].value[0] = 0;
  119.         fParameters[i].dialogItem = 0;
  120.     }
  121.     
  122.     for (i = 0; i < kStyledTextCount; i++)
  123.     {
  124.         fStyleTextItem[i] = 0;
  125.         fStyledText[i] = NULL;        
  126.     }
  127.  
  128.     fUserItemCallback = NewUserItemProc(CDialog::UserItemCallback);
  129.  
  130.     // Add it to the list of dialogs
  131.     SetNextDialog(gDialogList);
  132.     gDialogList = this;
  133.     
  134.     fDialogFont.SetFont(smSystemScript, fontCode);
  135. }
  136.  
  137.  
  138.  
  139. // --------------------------------------------------------------------
  140. // ~CDialog
  141. // --------------------------------------------------------------------
  142.  
  143. CDialog::~CDialog(void)
  144. {
  145.     for (int i = 0; i < kStyledTextCount; i++)
  146.     {
  147.         if (fStyleTextItem[i] != 0 && fStyledText[i] != NULL)
  148.         {
  149.             TEDispose(fStyledText[i]);
  150.         }
  151.     }
  152.  
  153.     if (fUserItemCallback != NULL)
  154.         DisposeRoutineDescriptor(fUserItemCallback);
  155.  
  156.     // remove this from the list of dialogs
  157.     if (gDialogList == this)
  158.     {
  159.         gDialogList = GetNextDialog();
  160.     }
  161.     else if (gDialogList != NULL)
  162.     {
  163.         for (CDialog *theDialog = gDialogList; theDialog != NULL; 
  164.                 theDialog = theDialog->GetNextDialog())
  165.         {
  166.             if (theDialog->GetNextDialog() == this)
  167.             {
  168.                 theDialog->SetNextDialog(this->GetNextDialog());
  169.                 break;
  170.             }
  171.         }
  172.     }
  173.  
  174.     if (fShortcuts != NULL)
  175.         DisposePtr((Ptr)fShortcuts);
  176. }
  177.  
  178.  
  179.  
  180. // --------------------------------------------------------------------
  181. // Close
  182. // --------------------------------------------------------------------
  183.  
  184. void CDialog::Close(void)
  185. {
  186.     if (GetDialogRef() != NULL)
  187.     {
  188.         // Get all the parameters
  189.         for (int i = 0; i < kDialogParametersCount; i++)
  190.         {
  191.             if (fParameters[i].dialogItem > 0)
  192.             {
  193.                 GetItemText(fParameters[i].dialogItem, fParameters[i].value);
  194.             }
  195.         }
  196.  
  197.     
  198.         ::DisposeDialog(GetDialogRef());
  199.         fDialog = NULL;
  200.         // In fact, DisposeDialog also dispose of the window, 
  201.         // therefore...
  202.         fWindow = NULL;
  203.     }
  204. }
  205.  
  206.  
  207.  
  208. // --------------------------------------------------------------------
  209. // GetCDialog
  210. // --------------------------------------------------------------------
  211.  
  212. CDialog* CDialog::GetCDialog(DialogRef dialog)
  213. {
  214.     CDialog *theDialog;
  215.     for (theDialog = gDialogList; theDialog != NULL; 
  216.             theDialog = theDialog->GetNextDialog())
  217.     {
  218.         if (theDialog->GetDialogRef() == dialog)
  219.             break;
  220.     }
  221.     return theDialog;
  222. }
  223.  
  224.  
  225.  
  226. // --------------------------------------------------------------------
  227. // Draw
  228. // --------------------------------------------------------------------
  229.  
  230. void CDialog::Draw(TDrawContext& drawContext)
  231. {
  232. #pragma unused(drawContext)
  233.  
  234. }
  235.  
  236.  
  237.  
  238. // --------------------------------------------------------------------
  239. // SetItemRect
  240. // --------------------------------------------------------------------
  241.  
  242. void CDialog::SetItemRect(short item, const CRect& newRect)
  243. {
  244.     CRect r;
  245.     Handle h;
  246.     short type;
  247.     
  248.     ::GetDialogItem(GetDialogRef(), item, &type, &h, r);
  249.     if (newRect != r)
  250.     {
  251.         if ((type & ctrlItem) == ctrlItem)
  252.         {
  253.             ::MoveControl((ControlRef)h, newRect.Left(), newRect.Top());
  254.         }
  255.         else if ((type & editText) == editText && 
  256.                 (((DialogPeek)GetDialogRef())->editField + 1) == item)
  257.         {
  258.             TEHandle te = ((DialogPeek)GetDialogRef())->textH;
  259.             ::TEDeactivate(te);
  260.             (**te).viewRect = (**te).destRect = newRect;
  261.             ::TECalText(te);
  262.             ::TEActivate(te);
  263.         }
  264.         ::SetDialogItem(GetDialogRef(), item, type, h, newRect);
  265.     }
  266. }
  267.  
  268.  
  269.  
  270. // --------------------------------------------------------------------
  271. // SetItemControl
  272. // --------------------------------------------------------------------
  273.  
  274. void CDialog::SetItemControl(short item, ControlRef control)
  275. {
  276.     Handle h = GetItemData(item);
  277.     if (h != NULL)
  278.         ::DisposeControl((ControlRef)h);
  279.     SetItemData(item, (Handle)control);
  280. }
  281.  
  282.  
  283.  
  284. // --------------------------------------------------------------------
  285. // SetItemText
  286. // --------------------------------------------------------------------
  287.  
  288. void CDialog::SetItemText(short item, ConstStr255Param s)
  289. {
  290.     assert(GetItemType(item) == statText || 
  291.             GetItemType(item) == editText);
  292.  
  293.     Handle h = GetItemData(item);
  294.     Str255 s2;
  295.     GetDialogItemText(h, s2);
  296.     
  297.     // Set the text only if different, to avoid flickering
  298.     if (!EqualString(s, s2, true, true))
  299.         SetDialogItemText(h, s);
  300. }
  301.  
  302.  
  303.  
  304. // --------------------------------------------------------------------
  305. // PasteText
  306. // --------------------------------------------------------------------
  307.  
  308. void CDialog::PasteText(Ptr text, short size)
  309. {
  310.     TEHandle te = ((DialogPeek)GetDialogRef())->textH;
  311.     if ((**te).selEnd - (**te).selStart > 0)
  312.         TEDelete(te);
  313.     TEInsert(text, size, te);
  314. }
  315.  
  316.  
  317.  
  318. // --------------------------------------------------------------------
  319. // ItemHit
  320. // --------------------------------------------------------------------
  321.  
  322. void CDialog::ItemHit(short itemHit)
  323. {
  324.     if (itemHit == fDefaultButton)
  325.     {
  326.         if (CloseRequested())
  327.             Close();
  328.     }
  329.     else if (itemHit == fCancelButton)
  330.     {
  331.         Close();
  332.     }
  333. }
  334.  
  335.  
  336.  
  337. // --------------------------------------------------------------------
  338. // MakeWindow
  339. // --------------------------------------------------------------------
  340.  
  341. WindowRef CDialog::MakeWindow(void)
  342. {
  343.     fDialog = MakeDialog();
  344.     
  345.     DoPrepareDialog();
  346.  
  347.     return ::GetDialogWindow(fDialog);
  348. }
  349.  
  350.  
  351.  
  352. // --------------------------------------------------------------------
  353. // MakeDialog
  354. // --------------------------------------------------------------------
  355.  
  356. DialogRef CDialog::MakeDialog(void)
  357. {
  358.     assert(GetDialogRef() == NULL);
  359.     DialogRef newDialog;
  360.     
  361.     // We want color dialogs. However, the caller does not necessarily 
  362.     // provide a 'dctb' and there isn't a GetNewCDialog routine.  
  363.     // This requires allocating the dialog with NewCDialog.
  364.     
  365.     DialogTemplate **dlogTemplate = 
  366.             (DialogTemplate **)GetResource('DLOG', fDialogID); // (-)
  367.     assert(dlogTemplate != NULL);
  368.     
  369.     if (GetResource('dctb', fDialogID) != NULL)
  370.     {    
  371.         // CDialogs never come up until you show them explicitly!
  372.         (*dlogTemplate)->visible = false; 
  373.         newDialog = GetNewDialog(fDialogID, NULL, (WindowRef)-1); // (-)
  374.         assert(newDialog != NULL);
  375.     }
  376.     else
  377.     {
  378.         ::HLock((Handle)dlogTemplate);
  379.  
  380.         Handle itemList = ::GetResource('DITL', (**dlogTemplate).itemsID);
  381.         assert(itemList != NULL);
  382.         ::DetachResource(itemList);
  383.  
  384.         newDialog = ::NewColorDialog(NULL, &(**dlogTemplate).boundsRect, 
  385.                         (**dlogTemplate).title, false, 
  386.                         (**dlogTemplate).procID,
  387.                         (WindowRef)-1, (**dlogTemplate).goAwayFlag, 
  388.                         (**dlogTemplate).refCon, itemList); // (-)
  389.         assert(newDialog != NULL);
  390.  
  391.     }
  392.     
  393.     ::ReleaseResource((Handle)dlogTemplate); // (-)
  394.  
  395.     // Use the dialog font in the dialog's grafport
  396.     fDialogFont.SetPortFont(GetGrafPtr());
  397.     
  398.     return newDialog;
  399. }
  400.  
  401.  
  402.  
  403. // --------------------------------------------------------------------
  404. // CheckKeyboardShortcuts
  405. // --------------------------------------------------------------------
  406.  
  407. Boolean CDialog::CheckKeyboardShortcuts(const EventRecord &event)
  408. {
  409.     Boolean result = false;
  410.     short itemHit = 0;
  411.     
  412.     if (GetDialogRef() != NULL)
  413.     {
  414.         if (event.what == keyDown)
  415.         {
  416.             switch (event.message & charCodeMask) 
  417.             {
  418.                 case 0x0d:
  419.                 case 0x03:
  420.                     itemHit = fDefaultButton;
  421.                     break;
  422.             
  423.                 case 0x1b:
  424.                     itemHit = fCancelButton;
  425.                     break;
  426.                     
  427.                 case 0x2E:
  428.                     if (event.modifiers & cmdKey)
  429.                         itemHit = fCancelButton;
  430.                     break;
  431.                 default:
  432.                     break;
  433.             }
  434.         }
  435.         
  436.         if (fShortcuts != NULL && itemHit == 0 && 
  437.             event.what == keyDown && (event.modifiers & cmdKey) != 0)
  438.         {
  439.             char c = (event.message & 0xff);
  440.             for (int i = 0; i < fNumShortcuts && !result; i++)
  441.             {
  442.                 if (fShortcuts[i].key == c)
  443.                 {
  444.                     itemHit = fShortcuts[i].item;
  445.                     result = true;
  446.                 }
  447.             }
  448.         }
  449.         
  450.         // Items that are controls want some extra handling.
  451.         // Too bad we can't handle radio buttons!
  452.         if (itemHit >= 1 && itemHit <= CountDITL(GetDialogRef()))
  453.         {
  454.             if ((GetItemType(itemHit) & ctrlItem) == ctrlItem)
  455.             {
  456.                 if (IsEnabled(itemHit))
  457.                 {
  458.                     switch (GetItemType(itemHit) & ~ctrlItem)
  459.                     {
  460.                     case btnCtrl:
  461.                         FlashButton(itemHit);
  462.                         break;
  463.                     case chkCtrl:
  464.                         SetItemValue(itemHit, !GetItemValue(itemHit));
  465.                         break;
  466.                     }
  467.                 }
  468.                 else
  469.                 {
  470.                     // The item was disabled
  471.                     itemHit = 0;
  472.                     result = false;
  473.                 }
  474.             }
  475.             if (itemHit > 0)
  476.                 ItemHit(itemHit);
  477.         }
  478.     }
  479.     return result;
  480. }
  481.  
  482.  
  483.  
  484. // --------------------------------------------------------------------
  485. // GetStyledText
  486. // --------------------------------------------------------------------
  487.  
  488. TEHandle CDialog::GetStyledText(short item)
  489. {
  490.     TEHandle result = NULL;
  491.  
  492.     for (int i = 0; i < kStyledTextCount; i++)
  493.     {
  494.         if (fStyleTextItem[i] == item)
  495.         {
  496.             result = fStyledText[i];
  497.             break;
  498.         }
  499.     }
  500.     
  501.     return result;
  502. }
  503.  
  504.  
  505.  
  506. // --------------------------------------------------------------------
  507. // SetStyledText
  508. // --------------------------------------------------------------------
  509.  
  510. void CDialog::SetStyledText(short item, TEHandle styledText)
  511. {
  512.     for (int i = 0; i < kStyledTextCount; i++)
  513.     {
  514.         if (fStyleTextItem[i] == item)
  515.         {
  516.             if (fStyledText[i] != NULL)
  517.             {
  518.                 TEDispose(fStyledText[i]);
  519.             }
  520.             fStyledText[i] = styledText;
  521.             break;
  522.         }
  523.     }
  524.     
  525.     if (i == kStyledTextCount)
  526.     {
  527.         // No existing items were found
  528.         for (i = 0; i < kStyledTextCount; i++)
  529.         {
  530.             if (fStyleTextItem[i] <= 0)
  531.             {
  532.                 fStyleTextItem[i] = item;
  533.                 fStyledText[i] = styledText;
  534.                 break;
  535.             }
  536.         }
  537.     }
  538. }
  539.  
  540.  
  541.  
  542. // --------------------------------------------------------------------
  543. // FilterEvent
  544. // --------------------------------------------------------------------
  545.  
  546. Boolean CDialog::FilterEvent(const EventRecord& event)
  547. {
  548.     Boolean result = false;
  549.     
  550.     if (CWindow::FilterEvent(event))
  551.     {
  552.         result = true;
  553.     }
  554.     else if (CheckKeyboardShortcuts(event))
  555.     {
  556.         // It was a keyboard shortcut
  557.         result = true;
  558.     }
  559.     else if (event.what == keyDown && (event.modifiers & cmdKey) != 0)
  560.     {
  561.         // This is an unknown keyboard shortcuts, pass it up
  562.         result = false;
  563.     }
  564.     else if (IsDialogEvent(&event))
  565.     {
  566.         short itemHit;
  567.         
  568.         // call the standard event filter
  569.         {
  570.             EventRecord eventCopy = event;
  571.             result = StdFilterProc(GetDialogRef(), &eventCopy, &itemHit);
  572.         }
  573.         
  574.         if (!result)
  575.         {
  576.             CFontSpec saveFontSpec;
  577.             saveFontSpec.Save();
  578.             
  579.             {
  580.                 fDialogFont.Use();
  581.                 {
  582.                     DialogRef dialog;
  583.                     if (event.what == mouseDown)
  584.                     {
  585.                         ControlRef control = GetItemControl(1);
  586.                     }
  587.                     if (DialogSelect(&event, &dialog, &itemHit))
  588.                         result = true;
  589.                 }
  590.             }
  591.             saveFontSpec.Restore();
  592.         }
  593.         
  594.         if (result)
  595.             ItemHit(itemHit);
  596.     }
  597.     
  598.     return result;
  599. }
  600.  
  601.  
  602.  
  603. // --------------------------------------------------------------------
  604. // DoPrepareDialog
  605. // --------------------------------------------------------------------
  606.  
  607. void CDialog::DoPrepareDialog(void)
  608. {
  609.     TDrawContext drawContext((GrafPtr)GetWindowPort(
  610.                                         GetDialogWindow(fDialog)));
  611.     if (drawContext.Lock())
  612.     {
  613.         // Set the clip region to empty to avoid blinking
  614.         RgnHandle saveRegion;
  615.         saveRegion = NewRgn();
  616.         GetClip(saveRegion);
  617.         
  618.         ClipRect(CRect(0, 0, 0, 0));
  619.  
  620.         PrepareDialog();
  621.         
  622.         SetClip(saveRegion);
  623.         DisposeRgn(saveRegion);
  624.         
  625.         drawContext.Unlock();
  626.     }
  627. }
  628.  
  629.  
  630.  
  631. // --------------------------------------------------------------------
  632. // PrepareDialog
  633. // --------------------------------------------------------------------
  634.  
  635. void CDialog::PrepareDialog(void)
  636. {
  637.     LazyHandle itemText;
  638.     SInt16 focusedEditField = 0;
  639.     
  640.     // Replace parameters in the dialog
  641.     SubstituteParameters();
  642.     
  643.     for (int i = 0; i < kStyledTextCount; i++)
  644.     {
  645.         if (fStyleTextItem[i] != 0 && fStyledText[i] != NULL)
  646.             ::TEDispose(fStyledText[i]);
  647.         fStyleTextItem[i] = 0;
  648.         fStyledText[i] = NULL;        
  649.     }
  650.  
  651.     // Use the dialog font
  652.     fDialogFont.Use();
  653.     
  654.     // Loop through all dialog items
  655.     for (int item = 1, itemCount = CountDITL(GetDialogRef());
  656.          item <= itemCount; item++)
  657.     {
  658.         short itemType = GetItemType(item);
  659.  
  660.         // Set the font if it is the first text field
  661.         if (itemType == kEditTextDialogItem && focusedEditField == 0)
  662.         {
  663.             TEHandle te = ((DialogPeek)GetDialogRef())->textH;
  664.             (**te).txSize = fDialogFont.GetSize();
  665.             (**te).txFont = fDialogFont.GetFont();
  666.             ::TECalText(te);
  667.         
  668.             // Set the selection to the first edit field
  669.             focusedEditField = item;
  670.             SelectItemText(focusedEditField);
  671.         }
  672.         
  673.         if (itemType == kStaticTextDialogItem)
  674.         {
  675.             TEHandle textEdit;
  676.             Str255 itemTextString;
  677.             GetItemText(item, itemTextString);
  678.             itemText.Set(&itemTextString[1], itemTextString[0]);
  679.             ConvertHTMLToStyledText(itemText, GetItemRect(item), &textEdit);
  680.             if (textEdit != NULL)
  681.             {
  682.                 SetStyledText(item, textEdit);
  683.                 SetItemType(item, userItem);
  684.                 ::InvalRect(GetItemRect(item));
  685.                 itemType = userItem;
  686.             }
  687.         }
  688.         
  689.         // Re-route user items to our callback
  690.         if (itemType == userItem)
  691.             SetDrawingProc(item, fUserItemCallback);            
  692.     }
  693.     
  694.     if (fDefaultButton > 0)
  695.         SetDefaultButton(fDefaultButton);
  696.     if (fCancelButton > 0)
  697.         SetCancelButton(fCancelButton);
  698.     ::SetDialogTracksCursor(GetDialogRef(), true);
  699. }
  700.  
  701.  
  702.  
  703. // --------------------------------------------------------------------
  704. // SubstituteParameters
  705. // --------------------------------------------------------------------
  706.  
  707. void CDialog::SubstituteParameters(void)
  708. {
  709.     // This routine will substitute parameters in the dialog, by 
  710.     // replacing any instance of a key, for example <name>, appearing
  711.     // in a static or editable text dialog item, by a corresponding 
  712.     // value.
  713.     // In addition, if an editable text item only contains a key, 
  714.     // the value entered in the dialog will be associated with the key.
  715.     // This is an extended version of the "^0" parameter substitution 
  716.     // done by the Dialog Manager.
  717.     
  718.     LazyHandle substitutionText;
  719.     LazyHandle itemText;
  720.     
  721.     // Reset the association between parameters and dialog items
  722.     for (int i = 0; i < kDialogParametersCount; i++)
  723.         fParameters[i].dialogItem = 0;
  724.  
  725.     // Loop through all dialog items
  726.     for (int item = 1, itemCount = ::CountDITL(GetDialogRef());
  727.          item <= itemCount; item++)
  728.     {
  729.         SInt16 itemType = GetItemType(item);
  730.  
  731.         // If a static or editable text item...
  732.         if (itemType == kEditTextDialogItem || 
  733.             itemType == kStaticTextDialogItem)
  734.         {
  735.             Boolean itemTextChanged = false;
  736.             
  737.             // Copy the text to a handle
  738.             Str255 itemTextString;
  739.             GetItemText(item, itemTextString);
  740.             itemText.Set(&itemTextString[1], itemTextString[0]);
  741.             
  742.             // Loop through the parameters
  743.             for (int j = 0; j < kDialogParametersCount; j++)
  744.             {
  745.                 // If the parameter is used, i.e., as a non-empty key
  746.                 if (fParameters[j].key[0] != 0)
  747.                 {
  748.                     if (itemType == kEditTextDialogItem && 
  749.                         ::IdenticalString(itemTextString, fParameters[j].key,
  750.                          NULL) == 0)
  751.                     {
  752.                         // If the edit field only contains the key,
  753.                         // associate the item index with the parameter.
  754.                         // The value of the parameter will be updated 
  755.                         // when the text changes
  756.                         fParameters[j].dialogItem = item;
  757.                     }
  758.                      {
  759.                          // Replace the key by the value of the parameter
  760.                          // using the Script Manager
  761.                         substitutionText.Set(&fParameters[j].value[1], 
  762.                                 fParameters[j].value[0]);
  763.                         if (::ReplaceText(itemText, substitutionText, 
  764.                                                 fParameters[j].key) > 0)
  765.                             itemTextChanged = true;
  766.                     }
  767.                 }
  768.             }
  769.             
  770.             if (itemTextChanged)
  771.             {
  772.                 // The text of the item has changed, put the 
  773.                 // modified text back in the dialog item
  774.                 Str255 s;
  775.                 
  776.                 s[0] = itemText.GetSize();
  777.                 ::BlockMoveData(*itemText, &s[1], s[0]);
  778.  
  779.                 SetItemText(item, s);
  780.                 
  781.                 // Invalidate the rectangle of the item so 
  782.                 // it gets updated.
  783.                 // Although SetItemText draws the new text immediately,
  784.                 // the clip region may be set to NULL by the caller to
  785.                 // avoid flashing
  786.                 ::InvalRect(GetItemRect(item));
  787.             }
  788.         }
  789.         
  790.     }
  791. }
  792.  
  793.  
  794.  
  795. // --------------------------------------------------------------------
  796. // DrawUserItem
  797. // --------------------------------------------------------------------
  798.  
  799. void CDialog::DrawUserItem(TDrawContext& graphics, short item, 
  800.                             const CRect& frame)
  801. {
  802. #pragma unused(graphics)
  803.  
  804.     // If there is a styled text record associated with this item,
  805.     // draw it now
  806.     TEHandle styledText = GetStyledText(item);
  807.     
  808.     if (styledText != NULL)
  809.     {
  810.         TEUpdate(frame, styledText);
  811.     }
  812.  
  813. }
  814.  
  815.  
  816.  
  817. // --------------------------------------------------------------------
  818. // AddKeyboardShortcuts
  819. // --------------------------------------------------------------------
  820.  
  821. void CDialog::AddKeyboardShortcuts(short stringID)
  822. {
  823.     assert(fNumShortcuts == 0);
  824.     assert(fShortcuts == NULL);
  825.     short **numShortcuts = (short **)GetResource('STR#', stringID);
  826.     if (numShortcuts != NULL)
  827.     {
  828.         assert(**numShortcuts >= 0);
  829.         fShortcuts = (Shortcut*)NewPtr(sizeof(Shortcut) * 
  830.                                                     (**numShortcuts));
  831.         if (fShortcuts != NULL)
  832.         {
  833.             for (int i = 1; i <= **numShortcuts; i++)
  834.             {
  835.                 Str255 s;
  836.                 ::GetIndString(s, stringID, i);
  837.                 assert(s[0] > 2);
  838.                 assert(s[2] == ':');
  839.                 fShortcuts[fNumShortcuts].key = s[1];
  840.                 s[2] = s[0] - 2;
  841.                 long n;
  842.                 ::StringToNum(s + 2, &n);
  843.                 fShortcuts[fNumShortcuts].item = n;
  844.                 fNumShortcuts++;
  845.             }
  846.         }
  847.     }
  848. }
  849.  
  850.  
  851.  
  852. // --------------------------------------------------------------------
  853. // FirstTextField
  854. // --------------------------------------------------------------------
  855.  
  856. short CDialog::FirstTextField(void)
  857. {
  858.     short result = 0;
  859.     
  860.     short curItem;
  861.     
  862.     short itemCount = ::CountDITL(GetDialogRef());
  863.     
  864.     // Loop thru the items in the dialog after curItem
  865.     for (curItem = 1;  curItem <= itemCount; curItem++)
  866.     {
  867.         if (GetItemType(curItem) == editText)
  868.         {
  869.             result = curItem;
  870.             break;
  871.         }
  872.     }
  873.     
  874.     return result;
  875. }
  876.  
  877.  
  878.  
  879. // --------------------------------------------------------------------
  880. // LastTextField
  881. // --------------------------------------------------------------------
  882.  
  883. short CDialog::LastTextField(void)
  884. {
  885.     short result = 0;
  886.     
  887.     short curItem = ::CountDITL(GetDialogRef());
  888.     
  889.     // Loop thru the items in the dialog before curItem
  890.     for (; curItem > 0; curItem--)
  891.     {
  892.         if (GetItemType(curItem) == editText)
  893.         {
  894.             result = curItem;
  895.             break;
  896.         }
  897.     }
  898.     
  899.     return result;
  900. }
  901.  
  902.  
  903.  
  904. // --------------------------------------------------------------------
  905. // FirstTextField
  906. // --------------------------------------------------------------------
  907.  
  908. short CDialog::PreviousTextField(short item)
  909. {
  910.     short result = 0;
  911.     
  912.     short curItem;
  913.     
  914.     if (item == 0)
  915.     {
  916.         // if item was 0, start from the item after the current one.
  917.         // Add 1 because editField is in range [0..n]
  918.         curItem = ((DialogPeek)GetDialogRef())->editField + 1;
  919.     }
  920.  
  921.     // Loop thru the items in the dialog before curItem
  922.     for (curItem = curItem - 1; curItem > 0; curItem--)
  923.     {
  924.         if (GetItemType(curItem) == editText)
  925.         {
  926.             result = curItem;
  927.             break;
  928.         }
  929.     }
  930.     
  931.     return result;
  932. }
  933.  
  934.  
  935.  
  936. // --------------------------------------------------------------------
  937. // NextTextField
  938. // --------------------------------------------------------------------
  939. // Returns the ID of the next text field in the dialog,
  940. // or 0 if no more text fields
  941.  
  942. short CDialog::NextTextField(short item)
  943. {
  944.     short result = 0;
  945.     
  946.     short curItem;
  947.     
  948.     if (item == 0)
  949.     {
  950.         // if item was 0, start from the item after the current one.
  951.         // Add 1 because editField is in range [0..n]
  952.         curItem = ((DialogPeek)GetDialogRef())->editField + 1;
  953.     }
  954.     
  955.     short itemCount = ::CountDITL(GetDialogRef());
  956.     
  957.     // Loop thru the items in the dialog after curItem
  958.     for (curItem = curItem + 1;  curItem <= itemCount; curItem++)
  959.     {
  960.         if (GetItemType(curItem) == editText)
  961.         {
  962.             result = curItem;
  963.             break;
  964.         }
  965.     }
  966.     
  967.     return result;
  968. }
  969.  
  970.  
  971.  
  972. // --------------------------------------------------------------------
  973. // SetParameter
  974. // --------------------------------------------------------------------
  975.  
  976. void CDialog::SetParameter(ConstStr15Param key, ConstStr255Param value)
  977. {
  978.     assert(key[0] <= 15);
  979.     assert(key[0] > 0);
  980.     
  981.     for (SInt16 i = 0; i < kDialogParametersCount; i++)
  982.     {
  983.         if (IdenticalString(key, fParameters[i].key, NULL) == 0 || 
  984.                                                 fParameters[i].key[0] == 0)
  985.         {
  986.             ::BlockMoveData(key, fParameters[i].key, key[0] + 1);
  987.             ::BlockMoveData(value, fParameters[i].value, value[0] + 1);
  988.             break;
  989.         }
  990.     }
  991. }
  992.  
  993.  
  994.  
  995. // --------------------------------------------------------------------
  996. // GetParameter
  997. // --------------------------------------------------------------------
  998.  
  999. void CDialog::GetParameter(ConstStr15Param key, Str255 value)
  1000. {
  1001.     assert(key[0] <= 15);
  1002.     assert(key[0] > 0);
  1003.     
  1004.     for (SInt16 i = 0; i < kDialogParametersCount; i++)
  1005.     {
  1006.         if (IdenticalString(key, fParameters[i].key, NULL) == 0)
  1007.         {
  1008.             if (fParameters[i].dialogItem > 0)
  1009.             {
  1010.                 GetItemText(fParameters[i].dialogItem, fParameters[i].value);
  1011.             }
  1012.             ::BlockMoveData(fParameters[i].value, value, 
  1013.                                             fParameters[i].value[0] + 1);
  1014.             break;
  1015.         }
  1016.     }
  1017. }
  1018.  
  1019.  
  1020.  
  1021. // --------------------------------------------------------------------
  1022. // SetCancelButton
  1023. // --------------------------------------------------------------------
  1024.  
  1025. void CDialog::SetCancelButton(short itemNumber)
  1026. {
  1027.     assert(itemNumber > 0);
  1028.     
  1029.     fCancelButton = itemNumber;
  1030.     ::SetDialogCancelItem(GetDialogRef(), itemNumber);
  1031. }
  1032.  
  1033.  
  1034.  
  1035. // --------------------------------------------------------------------
  1036. // SetDefaultButton
  1037. // --------------------------------------------------------------------
  1038.  
  1039. void CDialog::SetDefaultButton(short itemNumber)
  1040. {
  1041.     assert(itemNumber > 0);
  1042.  
  1043.     short oldDefault = fDefaultButton;
  1044.     
  1045.     // set the new default button
  1046.     fDefaultButton = itemNumber;
  1047.     ::SetDialogDefaultItem(GetDialogRef(), itemNumber);
  1048.     
  1049.     // Update the old button
  1050.     if (oldDefault > 0)
  1051.     {
  1052.         CRect r = GetItemRect(oldDefault);
  1053.         r.InsetBy(-4);
  1054.         EraseRect(r);
  1055.         if (IsWindowHilited(GetWindowRef()))
  1056.         {
  1057.             UpdateDialog(GetDialogRef(), CTempRgn(r));
  1058.         }
  1059.     }
  1060.     
  1061.     // Update the new button
  1062.     if (itemNumber > 0 && oldDefault != itemNumber)
  1063.     {
  1064.         CRect r = GetItemRect(oldDefault);
  1065.         r.InsetBy(-4);
  1066.         EraseRect(r);
  1067.         if (IsWindowHilited(GetWindowRef()))
  1068.         {
  1069.             UpdateDialog(GetDialogRef(), CTempRgn(r));
  1070.         }
  1071.     }
  1072. }
  1073.  
  1074.  
  1075.  
  1076. // --------------------------------------------------------------------
  1077. // SetDefaultButtonName
  1078. // --------------------------------------------------------------------
  1079.  
  1080. void CDialog::SetDefaultButtonName(ConstStr63Param buttonName)
  1081. {
  1082.     assert(GetDialogRef() != NULL);
  1083.     assert(fDefaultButton > 0);
  1084.     SetItemTitle(fDefaultButton, buttonName);
  1085. }
  1086.  
  1087.  
  1088.  
  1089. // --------------------------------------------------------------------
  1090. // UserItemCallback
  1091. // --------------------------------------------------------------------
  1092.  
  1093. pascal void CDialog::UserItemCallback(DialogRef dialog, short item)
  1094. {
  1095.     CFontSpec saveFont;
  1096.     saveFont.Save();
  1097.     {
  1098.         // ??? Not sure that this clipping is quite necessary here
  1099.         CClip saveClip;
  1100.         saveClip.Save();
  1101.         {
  1102.             CDialog* dialogObject = CDialog::GetCDialog(dialog);
  1103.             assert(dialogObject != NULL);
  1104.             dialogObject->fDialogFont.Use();
  1105.              {
  1106.                 TDrawContextIterator iterator(dialogObject->GetGrafPtr(),
  1107.                                      dialogObject->GetItemRect(item));
  1108.                 
  1109.                 while (iterator != iterator.end())
  1110.                 {
  1111.                     if ((*iterator).Lock())
  1112.                     {
  1113.                         dialogObject->DrawUserItem(*iterator, item, 
  1114.                                         dialogObject->GetItemRect(item));
  1115.                         (*iterator).Unlock();
  1116.                     }
  1117.                     ++iterator;
  1118.                 }
  1119.             }
  1120.         }
  1121.         saveClip.Restore();
  1122.     }
  1123.     saveFont.Restore();
  1124. }
  1125.